home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / rs0422.zip / LEVEL1 / HDLSIO.AS < prev    next >
Text File  |  1990-10-28  |  18KB  |  642 lines

  1. *TITLE    HDLSIO - Z80 SIO HDLC DRIVER ROUTINES
  2.  
  3. ;  Driver routines to operate a port of a Zilog Z80-SIO in the SDLC/HDLC mode
  4. ;  for packet radio operations.  These routines operate in the half-duplex
  5. ;  mode.  The SIO RTS line is used to turn the transmitter on.  Transmission
  6. ;  of data will not begin until the SIO CTS line is asserted.
  7. ;
  8. ;  Interface to the main program is via subroutine calls.
  9. ;  Each call must be made with the address of the SIO data structure
  10. ;  in the IY register.  This data structure is as follows:
  11.  
  12. *INCLUDE STRUCT.LIB
  13. *INCLUDE RCONFIG.LIB
  14.  
  15. ;  Upon activation, the main program should call the HDLINT initialization
  16. ;  entry point to set up the SIO hardware.  It is only necessary to call this
  17. ;  routine once per SIO channel used.  This routine is called only after a
  18. ;  hardware reset as the routines will take care of all further SIO setup
  19. ;  and disabling for the proper mode (Tx or Rx).  When frame data is received,
  20. ;  the external subroutine NEXTHI will be called to accept each data byte
  21. ;  or to flag the end of frame.  When transmission is desired, the TXSKED entry
  22. ;  point must be called to schedule the transmission.  As each data byte is
  23. ;  required by the SIO transmitter, the external subroutine NEXTHO will
  24. ;  be called.  When this subroutine indicates the end of the data for the
  25. ;  current transmission, the transmission will be terminated and the SIO placed
  26. ;  back in receive mode.  The external subroutine HODONE will then be called.
  27. ;
  28. ;  All routines must be entered with the data structure address in IY.
  29. ;  IX and IY registers are not affected by any of these routines.
  30. ;  All external subroutines should return with IY unchanged.
  31. ;
  32. ;  ENTRY POINTS:
  33. ;
  34. ;    HDLI -    Initialization subroutine.  The SIO registers
  35. ;        will be initialized in the receive mode.
  36. ;    Entry:    No parameters.
  37. ;    Return:    All registers undefined.
  38. ;
  39. ;    XSKED -    Schedule transmission.
  40. ;    Entry:    No parameters.
  41. ;    Return:    All registers undefined.
  42. ;
  43. ;    CDS -    Carrier detect status reporting.
  44. ;    Entry:    No parameters required
  45. ;    Return:    A  = 0 if DCD off
  46. ;        A  = 0FFH if DCD on
  47. ;
  48. ;    GETSIO -     Convert HL from Channel # to SDS address
  49. ;    Entry:    HL = Channel number
  50. ;    Return:    HL = A(SDS) Block
  51. ;        Z Flag set if out of bounds (and then HL=0)
  52.  
  53. ;  EXTERNAL ROUTINES
  54. ;
  55. ;  All of these routines are called within interrupt service.
  56. ;  External routines may destroy any registers except IY and those specified
  57. ;  below with return parameters.
  58. ;
  59. ;    NXTHO -    Routine to supply next data byte for trans-
  60. ;        mission.
  61. ;    Entry:    No parameters
  62. ;    Return:    A  = 0FFH if next data byte
  63. ;           = 0 if end of message (more to follow)
  64. ;           = 1 if end of transmission (no CW id)
  65. ;           = 2 if end of transmission and id request
  66. ;        B  = next data byte (if A = 0FFH)
  67. ;
  68. ;    ODONE -    Routine at end of transmission.  Called after
  69. ;        receive mode is re-entered.  No parameters.
  70. ;
  71. ;    NXTHI -    Routine to accept received data.  All data
  72. ;        after a call with A = 0 is invalid if another
  73. ;        call with A = 0 occurs before a call with
  74. ;        A = 1.
  75. ;    Entry:    A  = 0FFH if next data byte
  76. ;        A  = 0 if start of frame
  77. ;        A  = 1 if end of frame
  78. ;        A  = 2 if frame aborted due to an error
  79. ;        B  = next data byte (if A = 0 or 0FFH)
  80. ;    Return:    A  = 0 if all ok
  81. ;        A  = FF if the frame should be aborted
  82.  
  83. *HEADING 'SIO Constants'
  84.  
  85.             ;COMMANDS:
  86. RESTXI    EQU    28H        ;Reset TX interrupt
  87. RESEXT    EQU    10H        ;Reset external interrupt
  88. RESTCR    EQU    80H        ;Reset TX CRC generator
  89. RESEOM    EQU    0C0H        ;Reset TX end of message
  90. RESERR    EQU    30H        ;Reset error status
  91.  
  92.             ;STATUS BITS AND MASKS, RR 0
  93. ABORT    EQU    7        ;Break/abort
  94. MABORT    EQU    80H
  95. EOM    EQU    6        ;TX underrun/EOM
  96. MEOM    EQU    40H
  97. CTS    EQU    5        ;Clear-to-send line
  98. MCTS    EQU    20H
  99. SYNC    EQU    4        ;SDLC Sync/Hunt line
  100. MSYNC    EQU    10H
  101. DCD    EQU    3        ;Data-carrier-detect line
  102. MDCD    EQU    08H
  103. TXBE    EQU    2        ;TX buffer empty
  104. MTXBE    EQU    04H
  105. RXBF    EQU    0        ;RX buffer full
  106. MRXBF    EQU    01H
  107.  
  108.             ;STATUS BITS AND MASKS, RR 1
  109. EOF    EQU    7        ;End of SDLC frame
  110. MEOF    EQU    80H
  111. FERR    EQU    6        ;Framing error
  112. MFERR    EQU    40H
  113. OVR    EQU    5        ;RX overrun
  114. MOVR    EQU    20H
  115. PERR    EQU    4        ;Parity error
  116. MPERR    EQU    10H
  117. MRES    EQU    0EH        ;Residue mask
  118. ALL    EQU    0        ;All sent
  119. MALL    EQU    1
  120.  
  121. RES8    EQU    0110B        ;Byte boundry residue
  122. MRTS    EQU    02H        ;Mask for RTS (WR 5)
  123. MDTR    EQU    80H        ;Mask for DTR (WR 5)
  124.  
  125.     GLOBAL    HDLI,XSKED
  126. ;    GLOBAL    CDS
  127.     GLOBAL    I_TBE,I_RBF,I_EXT,I_SRX
  128.     GLOBAL    SETTMR,TICK
  129.     PSECT    text
  130. *HEADING 'Callable Subroutines'
  131.  
  132. ;  HDLI - SIO initialization routine
  133.  
  134. HDLI:
  135.     LD    L,(IY+SINIT)    ;SIO init data pointer, Lo byte
  136.     LD    H,(IY+(SINIT+1));SIO init data pointer, Hi byte
  137.     LD    B,(IY+SINTL)    ;Length of init data
  138.     LD    C,(IY+CPORT)    ;SIO control port
  139. ;
  140. HDLI1:
  141.     OTIR            ;Init the SIO (rx mode)
  142.     XOR    A
  143.     LD    (IY+TSTA),A    ;Tx mode off (state 0)
  144.     LD    (IY+RSTA),A    ;Rx state 0 (hunt)
  145.     RET
  146.  
  147. ;  XSKED - Schedule transmission
  148.  
  149. XSKED:    CALL    STDWAIT        ;Start Dwait timer
  150.     RET    NZ        ;If DWAIT<>0 OR DWAIT==0 && DCD Return
  151. DWDONE:    CALL    RTSON        ;Start modem up
  152.     CALL    STTXD        ;Yes, Start TXDELAY timer
  153.     JP    Z,STFRM        ;Try to start the frame if TXD=0
  154.     RET
  155.  
  156. STDWAIT:
  157.     LD    (IY+TSTA),5    ;Tx state = 5
  158.     BIT    FULL,(IY+FLAG)    ;Full Duplex port?
  159.     JP    Z,1f        ;Nope
  160.     XOR    A        ;Full Duplex port doesn't use DWait
  161.     RET
  162. 1:    LD    C,(IY+DWAT)    ;Get DWAIT value
  163.     LD    B,(IY+(DWAT+1))
  164.     LD    A,B        ;Check for no delay
  165.     OR    C        ;Well?
  166.     JP    NZ,2f        ;Start Timer
  167. ;                ;No timer, check for carrier
  168.     LD    C,(IY+CPORT)    ;SIO control register
  169.     IN    A,(C)        ;Get status
  170.     XOR    (IY+DCDTGL)    ;Adjust Sense of DCD Pin
  171.     BIT    DCD,A        ;Do we have a nasty carrier?
  172.     RET            ;If CCZ Then we can start sending (No DCD)
  173.  
  174. 2:    LD    A,R        ;Get a random number *EXPERIMENTAL*
  175.     AND    31        ;Make it 0-31 ms. (in tnc's it's 10ms steps)
  176.     ADD    A,C        ;Add it to the dwait
  177.     JP    NC,1f
  178.     INC    B        ;Handle the carry
  179. 1:    LD    C,A
  180.     PUSH    IY        ;Get structure base addr
  181.     POP    DE        ;Timer service argument
  182.     LD    HL,DSERVE    ;Where timer should call
  183.     LD    A,(IY+CHAN)    ;Get channel #
  184.     CALL    SETTMR        ;Set the timer
  185.     LD    (IY+TIMRUN),1    ;Show timer running
  186.     OR    1        ;Insure non-zero CC
  187.     RET
  188.  
  189. STTXD:
  190.     LD    (IY+TSTA),1    ;Tx state = 1
  191.     LD    C,(IY+TXDLY)    ;Get TXDLY value
  192.     LD    B,(IY+(TXDLY+1))
  193.     LD    A,B        ;Check for no delay
  194.     OR    C        ;Well?
  195.     RET    Z        ;No delay, skip timer
  196.     PUSH    IY        ;Get structure base addr
  197.     POP    DE        ;Timer service argument
  198.     LD    HL,TSERVE    ;Where timer should call
  199.     LD    A,(IY+CHAN)    ;Get channel #
  200.     CALL    SETTMR        ;Set the timer
  201.     LD    (IY+TIMRUN),2    ;Show timer running
  202.     OR    1        ;Insure non-zero return
  203.     RET
  204.  
  205. ;  CDS - DCD line status reporting subroutine
  206.  
  207. ;CDS:
  208. ;    LD    C,(IY+CPORT)    ;SIO control port
  209. ;    IN    A,(C)        ;Get ext status
  210. ;    BIT    DCD,A        ;Test DCD line
  211. ;    LD    A,0        ;Assume off
  212. ;    RET    Z
  213. ;    LD    A,0FFH        ;Flag it on
  214. ;    RET
  215.  
  216. ;   GETSIO - Get pointer to SDS struct given a Channel number
  217.  
  218.     GLOBAL    SDS0,GETSIO
  219. GETSIO:
  220.     PUSH    DE
  221.     LD    C,A        ;SAVE A, WE ONLY TRASH BC (AND USE HL)
  222.     LD    A,0        ;Insure H is 0
  223.     CP    H
  224.     JP    NZ,GETSIO0    ;Nope!
  225.     LD    A,L        ;Get Channel to search for
  226.     LD    HL,SDS0        ;First SDS channel is SDS0
  227.     LD    B,NUMCH
  228.     LD    DE,SDSLEN
  229. GNSIO:
  230.     CP    (HL)        ;CHAN is the first byte in the struc
  231.     JP    Z,GETSIO1    ;Found it!
  232.     ADD    HL,DE        ;Try next
  233.     DJNZ    GNSIO
  234. GETSIO0:
  235.     LD    HL,0        ;Not found.
  236. GETSIO1:
  237.     LD    A,L
  238.     OR    H        ;SET CC
  239.     LD    A,C        ;RESTORE A
  240.     POP    DE
  241.     RET
  242.  
  243. *HEADING 'Tx Buffer Empty Interrupt Service'
  244.  
  245. ;  Transmitter buffer empty interrupt service.
  246. ;  Action is as follows:
  247. ;    State 0 (idle transmitter)
  248. ;        Spurious interrupt -- ignore it.
  249. ;    State 1 (waiting for CTS/timer)
  250. ;        Spurious interrupt -- ignore it.
  251. ;    State 2 (transmitting data)
  252. ;        Call NEXTHO for data byte.  If NEXTHO
  253. ;        returns data, send to SIO.  Otherwise,
  254. ;        stuff dummy data to SIO. If end of
  255. ;        transmission, state = 3, else 4.
  256. ;    State 3 (end of frame)
  257. ;        Call STFRM to re-start transmission.
  258. ;        State = 2
  259. ;    State 4 (end of transmission)
  260. ;        Set RTS off, call HODONE to flag
  261. ;        end of transmission, state = 0.
  262. ;    State 5 (waiting for DWAIT timer)
  263. ;        the timer will be restarted by I_EXT
  264. ;        if a carrier is detected while running
  265. ;    State 6 (tx frame abort, virtual state)
  266. ;
  267. ;    State 7 (first EOT fill byte)
  268. ;        Send dummy data to SIO, state = 5.
  269. ;    State 8 (second EOT fill byte)
  270. ;        Send dummy data to SIO, state = 6.
  271.  
  272. I_TBE:
  273.     LD    A,(IY+TSTA)    ;Get current state
  274.     OR    A        ;Idle state (0)?
  275.     JR    Z,SPURTI    ;Yes, ignore int.
  276.     DEC    A        ;Waiting state (1)?
  277.     JR    NZ,TXS2        ;No
  278. SPURTI:    LD    C,(IY+CPORT)    ;SIO Control port
  279.     LD    A,RESTXI    ;Reset tx interrupt
  280.     OUT    (C),A
  281.     RET
  282.  
  283. TXS2:    DEC    A        ;Transmitting state (2)?
  284.     JR    NZ,TXS3        ;No
  285.     CALL    SIOTXCH        ;Get next byte
  286. ;    CALL    NEXTHO        ;Get next byte
  287.     OR    A        ;Is it a data byte?
  288.     LD    D,A        ;Save return code
  289.     JP    M,TXBYTE    ;Yes, send it
  290.     LD    C,(IY+CPORT)    ;SIO control port
  291.     LD    A,RESTXI    ;Reset the interrupt
  292.     OUT    (C),A
  293.     BIT    ASYNC,(IY+FLAG)    ;Is this an Async port?
  294.     JP    NZ,TXAS3    ;Async needs different handling
  295.     LD    A,D        ;Get NEXTHO return value
  296.     LD    (IY+TSTA),3    ;Assume end of frame
  297.     OR    A
  298.     RET    Z        ;NEXTHO says end of frame
  299.     LD    (IY+TSTA),7    ;NEXTHO says end of transmission, send fills
  300.     RET
  301.  
  302. TXAS3:    LD    A,D        ;Restore NEXTHO result
  303.     OR    A
  304.     JP    Z,STFRM        ;NEXTHO Says End of Frame, more to follow
  305.     LD    (IY+TSTA),6    ;NEXTHO Says End of TX, send fills
  306.     JP    TXS7        ;Inc State and send fill byte
  307.  
  308. TXBYTE:    LD    C,(IY+DPORT)    ;SIO data port
  309.     OUT    (C),B        ;Send data byte
  310.     RET
  311.  
  312. TXS3:    DEC    A        ;End of Frame state (3)?
  313.     JR    NZ,TXS4        ;No
  314.     JP    STFRM        ;Restart transmission (STFRM sets TSTA)
  315.  
  316. TXS4:    DEC    A        ;EOT? State (4)?
  317.     JP    Z,TXTERM    ;End of transmission (4)
  318.     DEC    A        ;Waiting for DWAIT Timer? (5)
  319.     JP    Z,SPURTI1    ;Yes, ignore INT
  320.     DEC    A        ;TX Frame Abort? (6)
  321.     JP    Z,SPURTI2    ;Yes, Ignore it (Does this happen?)
  322.     CP    4        ;Sending Fill Bytes (4 of'em) States 7-10
  323.     JP    P,TXTERM    ;State Out of Range, abort
  324.     JR    NZ,TXS7        ;Not done yet, just INC state
  325.     LD    (IY+TSTA),3    ;Will INC this to State 4
  326. TXS7:    INC    (IY+TSTA)    ;Advance to next state
  327.     LD    B,7Eh        ;Data for fill
  328.     JR    TXBYTE        ;Send fill
  329.  
  330. SPURTI1: JP    SPURTI
  331. SPURTI2: JP    SPURTI
  332.  
  333. TXTERM:    LD    (IY+TSTA),0    ;Show us stopped
  334.     CALL    RTSOFF        ;Stop transmitting
  335.     CALL    TXODONE        ;Report finish
  336. ;    CALL    HODONE        ;Report finish
  337.     RET
  338.  
  339. *HEADING 'External/Status Interrupt Service'
  340.  
  341. ;  External/status interrupt handler.  Check to see if
  342. ;  rx frame aborted or DCD lost.  If so, kill rx frame
  343. ;  by setting rx state to 0. Then, if the tx state is 0,
  344. ;  return.  Otherwise, tx is active, so we will
  345. ;  check the TX underrun status.  If underrun and tx state
  346. ;  is 2, execute  tx state 8 routine (terminataion).
  347. ;  If no underrun error, vector through either the CTS true
  348. ;  or CTS false state table, as appropriate.
  349.  
  350. I_EXT:
  351.     LD    C,(IY+CPORT)    ;SIO control port
  352.     LD    B,RESEXT    ;Reset external status
  353.     OUT    (C),B
  354.     IN    A,(C)        ;Get Current status register
  355.     XOR    (IY+DCDTGL)    ;Adjust DCD Sense
  356.     LD    E,A        ;Save Current Status in E
  357.     XOR    (IY+RR0)    ;Put Delta bits in A
  358.     LD    D,A        ;Save in D too
  359.     LD    (IY+RR0),E    ;Save real bits for next time
  360.  
  361. ;    E is Status; D (and A) are the Delta bits
  362.  
  363.     COND    CTC .eq. FALSE
  364.     BIT    TIMER,(IY+FLAG)    ;Are we on the port running the timer?
  365.     JR    Z,I_EXT0    ;Nope... Other port...
  366.     LD    HL,CLKBIT
  367.     AND    (HL)        ;Did the clock change state?  DR200
  368. ;    BIT    SYNC,A        ;Did the clock change state?  TNC
  369.     JP    Z,I_EXT0    ;No, Done
  370.     LD    HL,NUMTICK    ;Number of transitions to about 10ms
  371.     DEC    (HL)
  372.     JP    NZ,1f        ;No Tick Yet!
  373. ;    JP    NZ,I_EXT0    ;No Tick Yet!
  374.     LD    A,(TICKCNT)    ;GET NUMBER OF TICKS BEFORE EXECUTING
  375.     LD    (HL),A        ;Reset counter
  376.     CALL    TICK         ;My clock Ticked...
  377. 1:    LD    A,(CLKBIT)    ;WHAT ELSE CHANGED?
  378.     XOR    0FFH
  379.     AND    D        ;COPY ALL BITS, RESET CLOCK BIT
  380.     RET    Z        ;Nothing else changed
  381.     ENDC
  382.  
  383. I_EXT0:    BIT    ABORT,D        ;Break/Frame Abort Changed?
  384.     JP    NZ,RXABRT    ;Yes, DO IT!
  385. ;    LD    A,B        ;Restore status
  386. ;    AND    MABORT+MDCD    ;Mask all but Abort and DCD
  387.     LD    A,MDCD        ;Check for Carrier
  388.     AND    E        ;Currently present?
  389.     CP    MDCD        ;Status ok?
  390.     PUSH    DE        ;Save Status and Delta bits
  391.     CALL    NZ,RXABRT    ;No, Terminate rx frame
  392.     POP    DE        ;Restore Status...
  393.     LD    A,(IY+TSTA)    ;Get tx state
  394.     OR    A        ;Is TX Idle?
  395.     RET    Z        ;Yes, we don't care about the rest
  396.     CP    5        ;Waiting for DWAIT?
  397.     JP    NZ,I_EXT2    ;Nope, Maybe in State 2
  398.     BIT    DCD,E        ;Do we have a nasty carrier?
  399.     JR    Z,I_EXT1    ;Nope, see if timer is running...
  400.     CALL    STDWAIT        ;damn. Start dwait AGAIN!
  401.     RET            ;can't send if have dcd even if dwait=0
  402. I_EXT1:    LD    A,(IY+TIMRUN)    ;Is a timer running?
  403.     OR    A
  404.     RET    NZ        ;Yes, get out
  405.     JP    DWDONE        ;Start TX, if we can
  406.  
  407. I_EXT2:    CP    2        ;State 2 (data xfer)?
  408.     JR    NZ,I_XT10    ;No
  409.     BIT    EOM,E        ;Is underrun status?
  410.     JP    NZ,TXTERM    ;Terminate xmsn
  411. I_XT10:
  412. ;    BIT    CTS,E        ;Is CTS on?      ***DR200***
  413. ;    RET    Z        ;No, nothing to do
  414.     LD    A,(IY+TIMRUN)    ;Is timer running?
  415.     OR    A
  416.     RET    NZ        ;Yes, can't do anything
  417.     LD    A,(IY+TSTA)    ;Get tx state
  418.     CP    1        ;Waiting for it?
  419.     JR    Z,STFRM        ;Yes, start the frame
  420.     RET
  421.  
  422. *HEADING 'Internal Tx Subroutines'
  423.  
  424. ;  STFRM - Starts transmission of frame.
  425. ;  Call NEXTHO for data byte.  If none, ensure that RTS
  426. ;  is off and set tx state = 0.  Otherwise, reset Tx
  427. ;  CRC generator, send the data byte to the SIO and set
  428. ;  tx state = 2.
  429.  
  430. STFRM:    LD    (IY+TSTA),1    ;Waiting for CTS
  431.     LD    C,(IY+CPORT)    ;SIO control port
  432. ;    IN    A,(C)        ;Get RR0 Status
  433. ;    BIT    CTS,A        ;CTS on?    ***DR200***
  434. ;    RET    Z        ;Nope, Can't send yet...
  435.     BIT    ASYNC,(IY+FLAG)    ;Is this an Async port?
  436.     JP    NZ,1f        ;Yes, doesn't use CRC's
  437.     LD    A,RESTCR    ;Reset TX CRC
  438.     OUT    (C),A
  439. 1:    CALL    SIOTXCH        ;Get that byte
  440. ;1:    CALL    NEXTHO        ;Get that byte
  441.     OR    A
  442.     JP    P,TXTERM    ;No data waiting, why did we try and start?
  443.     LD    (IY+TSTA),2    ;State = 2
  444.     LD    C,(IY+DPORT)    ;SIO data port
  445.     OUT    (C),B        ;Send the data
  446.     LD    C,(IY+CPORT)    ;SIO control port
  447.     LD    A,RESEOM    ;Reset Tx EOM status
  448.     OUT    (C),A
  449.     RET
  450.  
  451. ;  RTSON - Turns RTS on
  452.  
  453. RTSON:
  454.     LD    C,(IY+CPORT)    ;SIO control port
  455.     LD    A,5        ;Select WR 5
  456.     OUT    (C),A
  457.     LD    A,(IY+WR5REG)    ;Get current WR 5 Settings
  458.     OR    (IY+PTTMSK1)
  459.     AND    (IY+PTTMSK2)    ;Set the RTS Bit Correctly
  460.     OUT    (C),A
  461.     LD    (IY+WR5REG),A    ;Save for later
  462.     RET
  463.  
  464. ;  RTSOFF - Turn RTS off
  465.  
  466. RTSOFF:
  467.     LD    C,(IY+CPORT)    ;SIO control port
  468.     LD    A,5        ;Select WR 5
  469.     OUT    (C),A
  470.     LD    A,(IY+WR5REG)    ;Get current setting
  471.     CPL
  472.     OR    (IY+PTTMSK1)
  473.     AND    (IY+PTTMSK2)
  474.     CPL
  475.     OUT    (C),A
  476.     LD    (IY+WR5REG),A    ;Save for later
  477.     RET
  478.  
  479. ;  DSERVE - Waiting for DWAIT to timeout
  480.  
  481. DSERVE:
  482.     PUSH    DE        ;Get data structure base
  483.     POP    IY
  484.     LD    (IY+TIMRUN),0    ;Show timer stopped
  485.  
  486.     LD    C,(IY+CPORT)    ;SIO control register
  487.     IN    A,(C)        ;Get status
  488.     XOR    (IY+DCDTGL)    ;Adjust Sense if needed
  489.     BIT    DCD,A        ;Do we have a nasty carrier?
  490.     JP    NZ,XSKED    ;If CCZ Then we can start sending (No DCD)
  491.  
  492.     JP    DWDONE        ;Start Sending!
  493.  
  494. ;  TSERVE - Timer service
  495.  
  496. TSERVE:
  497.     PUSH    DE        ;Get data structure base
  498.     POP    IY
  499.     LD    (IY+TIMRUN),0    ;Show timer stopped
  500.     JP    STFRM        ;Go check transmission
  501.  
  502. *HEADING 'Rx Buffer Full Interrupt Service'
  503.  
  504. ;  Receive buffer full interrupt routine.  Get received
  505. ;  char into B and exwcute based on receive state.
  506.  
  507. I_RBF:
  508.     LD    C,(IY+DPORT)    ;SIO data port
  509.     IN    B,(C)        ;Get received data byte
  510.     LD    A,(IY+RSTA)    ;Get rx state
  511.     OR    A        ;Is rx state 0?
  512.     JR    NZ,RS1        ;No
  513.  
  514. ;  Rx State 0, the idle state, is maintained until the first
  515. ;  receive interrupt.  Due to the fact that the SIO passes
  516. ;  FCS as data, a one byte buffer is used to insure that FCS
  517. ;  never gets passed to NEXTHI.
  518. ;  Store received char in buffer, state = 1
  519.  
  520.     LD    A,0        ;SOM For ASYNC
  521.     LD    (IY+RSTA),1    ;Next state = 1
  522.     BIT    ASYNC,(IY+FLAG)    ;Async port?
  523.     JP    NZ,RS2A        ;Just pass the byte up
  524.     LD    (IY+CBUF),B    ;Buffer received char
  525.     RET
  526.  
  527. RS1:    DEC    A        ;Is rx state 1?
  528.     JR    NZ,RS2
  529.  
  530. ;  Rx states 1 and 2 - Place the received char in the
  531. ;  buffer, sending the current buffer char to NEXTHI.
  532. ;  Set state = 2
  533.  
  534.     LD    A,0FFH        ;It's a Data byte for ASYNC
  535.     BIT    ASYNC,(IY+FLAG)    ;Async port?
  536.     JP    NZ,RS2A        ;Just pass the byte up
  537.     LD    (IY+RSTA),2    ;Next state = 2
  538.     LD    A,0        ;Flag SOM to NEXTHI
  539.     JR    GIVERX
  540.  
  541. RS2:    DEC    A        ;Insure we are in state 2
  542.     JR    NZ,RXTERM    ;Error, abort frame (Async Break Recd)
  543.     LD    A,0FFH        ;Flag next data byte to NEXTHI
  544.  
  545. GIVERX:    LD    C,(IY+CBUF)    ;Save buffer char
  546.     LD    (IY+CBUF),B    ;Buffer received char
  547.     LD    B,C        ;Get old buffer char
  548. RS2A:    CALL    SIORXCH        ;Give to upper level sub
  549. ;RS2A:    CALL    NEXTHI        ;Give to upper level sub
  550.     OR    A        ;WAS THERE AN ERROR?
  551.     RET    Z        ;Not yet... we're ok
  552. RXTERM:    XOR    A
  553.     OR    (IY+RSTA)    ;Only Abort once
  554.     RET    Z        ;Already Idle
  555.     LD    (IY+RSTA),0    ;Idle state
  556.     LD    A,2
  557.     CALL    SIORXCH
  558. ;    CALL    NEXTHI
  559.     RET
  560.  
  561.     global    OS_QUE, _ASYBRK ;, _PADFWD
  562. RXABRT:    BIT    ASYNC,(IY+FLAG)    ;Async line?
  563.     JP    Z,RXTERM    ;No, abort current frame
  564.     BIT    ABORT,D        ;Abort Changed?
  565.     JP    Z,RXTERM    ;Lost Carrier, abort frame
  566.     BIT    ABORT,E        ;Is it the Start of the Break?
  567.     LD    BC,1        ;Assume End of Break.
  568.     JP    Z,1f        ;It is...
  569.     LD    (IY+RSTA),0    ;Abort frame with Break Char
  570.     LD    A,1        ;Forward current rx frame when the
  571.     CALL    SIORXCH        ;Break sequence starts
  572.     LD    BC,0        ;Indicate Start of Break
  573. ;
  574. ;    Async Break Signal, call ASYBRK(chan)
  575. ;
  576. 1:    LD    HL,_ASYBRK    ;Function to call
  577.     LD    D,0
  578.     LD    E,(IY+CHAN)    ;Get Port number
  579.     LD    A,2        ;Two Args
  580.     CALL    OS_QUE
  581. ;    LD    A,0FFh
  582. ;    LD    (_PADFWD),A    ;Set flag to not forward buffer when idle
  583.     RET
  584.  
  585. ;  Special receive interrupt routine.  Occurs on error
  586. ;  or end of frame.  If in state 2 and no error,
  587. ;  execute state 3 routine (valid EOM).  If error status,
  588. ;  terminate frame.  Possible errors: CRC error, rx
  589. ;  underrun, invalid residue code (not 8-bit boundry)
  590.  
  591. I_SRX:
  592.     LD    C,(IY+CPORT)    ;SIO control port
  593.     LD    A,1        ;Set RR 1
  594.     OUT    (C),A
  595.     IN    A,(C)        ;Get special rx status
  596.     LD    B,A        ;Save it
  597.     LD    A,RESERR     ;Reset error status
  598.     OUT    (C),A
  599.     LD    C,(IY+DPORT)    ;SIO data port
  600.     IN    A,(C)        ;Get last FCS byte
  601.     LD    A,B        ;Get status
  602.     AND    MEOF+MFERR+MOVR+MRES
  603.                 ;Save the important bits
  604.     CP    MEOF+RES8    ;Proper end of frame?
  605.     JR    NZ,RXTERM    ;No, terminate frame
  606.     LD    A,(IY+RSTA)    ;We in state 2?
  607.     CP    2
  608.     JP    NZ,RXTERM    ;Can this frame
  609.     LD    A,1        ;NEXTHI final flag
  610.     CALL    SIORXCH        ;Tell NEXTHI is a good one
  611. ;    CALL    NEXTHI        ;Tell NEXTHI is a good one
  612.     LD    (IY+RSTA),0    ;Reset to state 0
  613.     RET
  614.  
  615.     GLOBAL    SIOTXCH, SIORXCH, TXODONE    ;These are now called directly
  616.     COND    0
  617. *HEADING 'External subroutine calls'
  618.  
  619. NEXTHO:
  620.     LD    L,(IY+NXTHO)    ;Get NXTHO address
  621.     LD    H,(IY+(NXTHO+1))
  622.     JP    (HL)
  623.  
  624. NEXTHI:
  625.     LD    L,(IY+NXTHI)    ;Get NXTHI address
  626.     LD    H,(IY+(NXTHI+1))
  627.     JP    (HL)
  628.  
  629. HODONE:
  630.     LD    L,(IY+ODONE)    ;Get ODONE address
  631.     LD    H,(IY+(ODONE+1))
  632.     JP    (HL)
  633.     ENDC
  634.  
  635.     GLOBAL    CLKBIT, TICKCNT
  636.  
  637.     PSECT    bss
  638. NUMTICK: DEFS    1
  639. CLKBIT:    DEFS    1
  640. TICKCNT: DEFS    1
  641.     END
  642.